package com.mzj.saas.sdk.refund.wx;

import cn.hutool.core.util.XmlUtil;
import com.mzj.saas.sdk.refund.vo.WxRefund;
import com.mzj.saas.sdk.util.WechatUtils;
import com.mzj.saas.sdk.wxsdk.WXPay;
import com.mzj.saas.sdk.wxsdk.WXPayUtil;
import com.mzj.saas.sdk.wxsdk.WxConfig;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 微信退款
 * 
 * @author hp
 *
 */
public class WxRefundRequest {

	private final static Logger logger = LoggerFactory.getLogger(WxRefundRequest.class);
	
	
	private WxRefund wxRefund;
	
	
	public WxRefundRequest(final WxRefund wxRefund) {
		this.wxRefund = wxRefund;
	}
	
	/**
	 * 微信退款
	 * api地址 ：https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
	 * @return null异常
	 * 
	 * return_code=SUCCESS && result_code=SUCCESS ==> 微信退款申请已提交,通过回调来确认是否退款成功
	 * 
	 */
	public Map<String, String> refund(){
		if(wxRefund == null) {
			logger.error("微信退款---------->wxRefund is null");
			return null;
		}
		try {
			SortedMap<String, Object> parameters = new TreeMap<String, Object>();
			parameters.put("appid", wxRefund.getAppId());
			parameters.put("mch_id", wxRefund.getMchId());
			
			if(StringUtils.isNotBlank(wxRefund.getTransactionId())) {
				parameters.put("transaction_id", wxRefund.getTransactionId());
			}
			
			if(StringUtils.isNotBlank(wxRefund.getOutTradeNo())) {
				parameters.put("out_trade_no",wxRefund.getOutTradeNo());
			}
			
			parameters.put("nonce_str", WechatUtils.generateNonceStr());
			parameters.put("out_refund_no", wxRefund.getOutRefundNo());
			parameters.put("total_fee", wxRefund.getTotalFee());
			parameters.put("refund_fee", wxRefund.getRefundFee());
			parameters.put("notify_url", wxRefund.getNotifyUrl());
			
			String sign = WechatUtils.getSign( parameters, wxRefund.getMchApiKey());
			parameters.put("sign", sign);
			
			byte[] certP12 = wxRefund.getMchCertificate();
			char[] mchIdArray = wxRefund.getMchId().toString().toCharArray();
	        InputStream inputStream = new ByteArrayInputStream(certP12);
	        KeyStore keyStore = KeyStore.getInstance("PKCS12");
	        keyStore.load(inputStream, mchIdArray);

	        if (inputStream != null) {
	            inputStream.close();
	        }
			
	        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchIdArray).build();
	        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"},
	                null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
	        HttpPost httpPost = new HttpPost(wxRefund.getRefundApi());
	        logger.info("WxPaybankService refundChange xml = {}", XmlUtil.mapToXmlStr(parameters), "UTF-8");
	        httpPost.setEntity(new StringEntity(XmlUtil.mapToXmlStr(parameters), "UTF-8"));
	        
	        // 加载含有证书的http请求
			// 2023/10/16  修改jdk中的java.security，将jdk.tls.disabledAlgorithms的key删除掉SSLv3, TLSv1, TLSv1.1
			//https://www.cnblogs.com/oktokeep/p/17158735.html	第三种方法
	        CloseableHttpResponse response = HttpClients.custom().setSSLSocketFactory(socketFactory).build().execute(httpPost);
	        String resultXml = EntityUtils.toString(response.getEntity(), "utf-8");
	        logger.info("WxPayService orderRefund = {}",resultXml);
	        Map<String, String> result = WechatUtils.doXMLParse(resultXml); // 将Xml转化为Map
		    return result;
		}catch(Exception e) {
			logger.error("微信退款异常" + e.getMessage(),e);
		}
		return null;
	}
	
	
	/**
	 * 查询退款状态
	 * 应用场景
                     提交退款申请后，通过调用该接口查询退款状态。退款有一定延时，用零钱支付的退款20分钟内到账，银行卡支付的退款3个工作日后重新查询退款状态
	 * @param outTradeNo
	 * @return
	 */
	public Map<String, String> refundquery(){
		try {
			 if(wxRefund == null) {
				logger.error("查询退款状态---------->wxRefund is null");
				return null;
			 }
			 WxConfig config = new WxConfig(wxRefund.getAppId(),wxRefund.getMchId(),wxRefund.getMchApiKey());
			 WXPay wxpay = new WXPay(config,null, true, false);
			 Map<String, String> map = new HashMap<>(16);
			 map.put("nonce_str", WXPayUtil.generateNonceStr());
			 
			 if(StringUtils.isNotBlank(wxRefund.getOutTradeNo())) {
				 map.put("out_trade_no", wxRefund.getOutTradeNo());
			 }
			 
			 if(StringUtils.isNotBlank(wxRefund.getTransactionId())) {
				 map.put("transaction_id", wxRefund.getTransactionId());
			 }
			 
			 if(StringUtils.isNotBlank(wxRefund.getOutRefundNo())) {
				 map.put("out_refund_no", wxRefund.getOutRefundNo());
			 }
			 
			 if(StringUtils.isNotBlank(wxRefund.getRefundId())) {
				 map.put("refund_id", wxRefund.getRefundId());
			 }
			 String sign = WXPayUtil.generateSignature(map, config.getKey());
			 map.put("sign", sign);
			 Map<String, String> resp = wxpay.refundQuery(map);
			 return resp;
		 }catch(Exception e) {
			 logger.error("查询退款状态异常" + e.getMessage(),e);
		 }
		 return null;
	}
}
